home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpuzzles.3 / xpuzzles / xpuzzles-5.3.1 / xskewb / Skewb2d.c < prev    next >
C/C++ Source or Header  |  1996-02-05  |  25KB  |  734 lines

  1. /*
  2. # X-BASED SKEWB
  3. #
  4. #  Skewb2d.c
  5. #
  6. ###
  7. #
  8. #  Copyright (c) 1994 - 96    David Albert Bagley, bagleyd@hertz.njit.edu
  9. #
  10. #                   All Rights Reserved
  11. #
  12. #  Permission to use, copy, modify, and distribute this software and
  13. #  its documentation for any purpose and without fee is hereby granted,
  14. #  provided that the above copyright notice appear in all copies and
  15. #  that both that copyright notice and this permission notice appear in
  16. #  supporting documentation, and that the name of the author not be
  17. #  used in advertising or publicity pertaining to distribution of the
  18. #  software without specific, written prior permission.
  19. #
  20. #  This program is distributed in the hope that it will be "playable",
  21. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  23. #
  24. */
  25.  
  26. /* Methods file for Skewb2d */
  27.  
  28. #include <stdio.h>
  29. #include <X11/IntrinsicP.h>
  30. #include <X11/Intrinsic.h>
  31. #include <X11/StringDefs.h>
  32. #include <X11/CoreP.h>
  33. #include "SkewbP.h"
  34. #include "Skewb2dP.h"
  35.  
  36. static void InitializeSkewb2D();
  37. static void ResizeSkewb2D();
  38. static void ExposeSkewb2D();
  39. static Boolean SetValuesSkewb2D();
  40. static void MoveSkewb2DTl();
  41. static void MoveSkewb2DTop();
  42. static void MoveSkewb2DTr();
  43. static void MoveSkewb2DLeft();
  44. static void MoveSkewb2dRight();
  45. static void MoveSkewb2DBl();
  46. static void MoveSkewb2DBottom();
  47. static void MoveSkewb2DBr();
  48. static void ResizePolyhedrons();
  49. static void DrawFrame();
  50. static void DrawOrientLine();
  51.  
  52. static char defaultTranslationsSkewb2D[] =
  53.   "<KeyPress>q: Quit()\n\
  54.    Ctrl<KeyPress>C: Quit()\n\
  55.    <KeyPress>KP_Divide: MoveCcw()\n\
  56.    <KeyPress>Home: MoveTl()\n\
  57.    <KeyPress>KP_7: MoveTl()\n\
  58.    <KeyPress>R7: MoveTl()\n\
  59.    <KeyPress>Up: MoveTop()\n\
  60.    <KeyPress>KP_8: MoveTop()\n\
  61.    <KeyPress>R8: MoveTop()\n\
  62.    <KeyPress>Prior: MoveTr()\n\
  63.    <KeyPress>KP_9: MoveTr()\n\
  64.    <KeyPress>R9: MoveTr()\n\
  65.    <KeyPress>Left: MoveLeft()\n\
  66.    <KeyPress>KP_4: MoveLeft()\n\
  67.    <KeyPress>R10: MoveLeft()\n\
  68.    <KeyPress>Begin: MoveCw()\n\
  69.    <KeyPress>KP_5: MoveCw()\n\
  70.    <KeyPress>R11: MoveCw()\n\
  71.    <KeyPress>Right: MoveRight()\n\
  72.    <KeyPress>KP_6: MoveRight()\n\
  73.    <KeyPress>R12: MoveRight()\n\
  74.    <KeyPress>End: MoveBl()\n\
  75.    <KeyPress>KP_1: MoveBl()\n\
  76.    <KeyPress>R1: MoveBl()\n\
  77.    <KeyPress>Down: MoveBottom()\n\
  78.    <KeyPress>KP_2: MoveBottom()\n\
  79.    <KeyPress>R14: MoveBottom()\n\
  80.    <KeyPress>Next: MoveBr()\n\
  81.    <KeyPress>KP_3: MoveBr()\n\
  82.    <KeyPress>R3: MoveBr()\n\
  83.    <Btn1Down>: Select()\n\
  84.    <Btn1Up>: Release()\n\
  85.    <KeyPress>p: Practice()\n\
  86.    <Btn2Down>(2+): Practice()\n\
  87.    <Btn2Down>: PracticeMaybe()\n\
  88.    <KeyPress>r: Randomize()\n\
  89.    <Btn3Down>(2+): Randomize()\n\
  90.    <Btn3Down>: RandomizeMaybe()\n\
  91.    <KeyPress>g: Get()\n\
  92.    <KeyPress>w: Write()\n\
  93.    <KeyPress>u: Undo()\n\
  94.    <KeyPress>s: Solve()\n\
  95.    <KeyPress>o: Orientize()";
  96.  
  97. static XtActionsRec actionsListSkewb2D[] =
  98. {
  99.   {"Quit", (XtActionProc) QuitSkewb},
  100.   {"MoveCcw", (XtActionProc) MoveSkewbCcw},
  101.   {"MoveTl", (XtActionProc) MoveSkewb2DTl},
  102.   {"MoveTop", (XtActionProc) MoveSkewb2DTop},
  103.   {"MoveTr", (XtActionProc) MoveSkewb2DTr},
  104.   {"MoveLeft", (XtActionProc) MoveSkewb2DLeft},
  105.   {"MoveCw", (XtActionProc) MoveSkewbCw},
  106.   {"MoveRight", (XtActionProc) MoveSkewb2dRight},
  107.   {"MoveBl", (XtActionProc) MoveSkewb2DBl},
  108.   {"MoveBottom", (XtActionProc) MoveSkewb2DBottom},
  109.   {"MoveBr", (XtActionProc) MoveSkewb2DBr},
  110.   {"Select", (XtActionProc) SelectSkewb},
  111.   {"Release", (XtActionProc) ReleaseSkewb},
  112.   {"Practice", (XtActionProc) PracticeSkewb},
  113.   {"PracticeMaybe", (XtActionProc) PracticeSkewbMaybe},
  114.   {"Randomize", (XtActionProc) RandomizeSkewb},
  115.   {"RandomizeMaybe", (XtActionProc) RandomizeSkewbMaybe},
  116.   {"Get", (XtActionProc) GetSkewb},
  117.   {"Write", (XtActionProc) WriteSkewb},
  118.   {"Undo", (XtActionProc) UndoSkewb},
  119.   {"Solve", (XtActionProc) SolveSkewb},
  120.   {"Orientize", (XtActionProc) OrientizeSkewb}
  121. };
  122.  
  123. static XtResource resourcesSkewb2D[] =
  124. {
  125.   {XtNfaceColor0, XtCLabel, XtRString, sizeof(String),
  126.    XtOffset(SkewbWidget, skewb.faceName[0]), XtRString, "Red"},
  127.   {XtNfaceColor1, XtCLabel, XtRString, sizeof(String),
  128.    XtOffset(SkewbWidget, skewb.faceName[1]), XtRString, "Blue"},
  129.   {XtNfaceColor2, XtCLabel, XtRString, sizeof(String),
  130.    XtOffset(SkewbWidget, skewb.faceName[2]), XtRString, "White"},
  131.   {XtNfaceColor3, XtCLabel, XtRString, sizeof(String),
  132.    XtOffset(SkewbWidget, skewb.faceName[3]), XtRString, "Green"},
  133.   {XtNfaceColor4, XtCLabel, XtRString, sizeof(String),
  134.    XtOffset(SkewbWidget, skewb.faceName[4]), XtRString, "Pink"},
  135.   {XtNfaceColor5, XtCLabel, XtRString, sizeof(String),
  136.    XtOffset(SkewbWidget, skewb.faceName[5]), XtRString, "Yellow"},
  137.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  138.    XtOffset(SkewbWidget, skewb.foreground), XtRString, XtDefaultForeground},
  139.   {XtNpieceBorder, XtCColor, XtRPixel, sizeof(Pixel),
  140.    XtOffset(SkewbWidget, skewb.borderColor), XtRString, XtDefaultForeground},
  141.   {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  142.    XtOffset(SkewbWidget, core.width), XtRString, "300"},
  143.   {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  144.    XtOffset(SkewbWidget, core.height), XtRString, "400"},
  145.   {XtNorient, XtCOrient, XtRBoolean, sizeof(Boolean),
  146.    XtOffset(SkewbWidget, skewb.orient), XtRString, "FALSE"}, /* DEFAULTORIENT */
  147.   {XtNmono, XtCMono, XtRBoolean, sizeof(Boolean),
  148.    XtOffset(SkewbWidget, skewb.mono), XtRString, "FALSE"},
  149.   {XtNface, XtCFace, XtRInt, sizeof(int),
  150.    XtOffset(SkewbWidget, skewb.currentFace), XtRString, "-1"},
  151.   {XtNpos, XtCPos, XtRInt, sizeof(int),
  152.    XtOffset(SkewbWidget, skewb.currentPosition), XtRString, "-1"},
  153.   {XtNdirection, XtCDirection, XtRInt, sizeof(int),
  154.    XtOffset(SkewbWidget, skewb.currentDirection), XtRString, "-1"},
  155.   {XtNpractice, XtCBoolean, XtRBoolean, sizeof(Boolean),
  156.    XtOffset(SkewbWidget, skewb.practice), XtRString, "FALSE"},
  157.   {XtNstart, XtCBoolean, XtRBoolean, sizeof(Boolean),
  158.    XtOffset(SkewbWidget, skewb.started), XtRString, "FALSE"},
  159.   {XtNselectCallback, XtCCallback, XtRCallback, sizeof(caddr_t),
  160.    XtOffset(SkewbWidget, skewb.select), XtRCallback, NULL}
  161. };
  162.  
  163. Skewb2DClassRec skewb2dClassRec =
  164. {
  165.   {
  166.     (WidgetClass) &skewbClassRec,    /* superclass */
  167.     "Skewb2D",                /* class name */
  168.     sizeof(Skewb2DRec),            /* widget size */
  169.     NULL,                /* class initialize */
  170.     NULL,                /* class part initialize */
  171.     FALSE,                /* class inited */
  172.     InitializeSkewb2D,            /* initialize */
  173.     NULL,                /* initialize hook */
  174.     XtInheritRealize,            /* realize */
  175.     actionsListSkewb2D,            /* actions */
  176.     XtNumber(actionsListSkewb2D),    /* num actions */
  177.     resourcesSkewb2D,            /* resources */
  178.     XtNumber(resourcesSkewb2D),        /* num resources */
  179.     NULLQUARK,                /* xrm class */
  180.     TRUE,                /* compress motion */
  181.     TRUE,                /* compress exposure */
  182.     TRUE,                /* compress enterleave */
  183.     TRUE,                /* visible interest */
  184.     NULL,                /* destroy */
  185.     ResizeSkewb2D,            /* resize */
  186.     ExposeSkewb2D,            /* expose */
  187.     SetValuesSkewb2D,            /* set values */
  188.     NULL,                /* set values hook */
  189.     XtInheritSetValuesAlmost,        /* set values almost */
  190.     NULL,                /* get values hook */
  191.     XtInheritAcceptFocus,        /* accept focus */
  192.     XtVersion,                /* version */
  193.     NULL,                /* callback private */
  194.     defaultTranslationsSkewb2D,        /* tm table */
  195.     NULL,                /* query geometry */
  196.     NULL,                /* display accelerator */
  197.     NULL                /* extension */
  198.   },
  199.   {
  200.     0                    /* ignore */
  201.   },
  202.   {
  203.     0                    /* ignore */
  204.   }
  205. };
  206.  
  207. WidgetClass skewb2dWidgetClass = (WidgetClass) &skewb2dClassRec;
  208.  
  209. static int planeToCube[MAXRECT] = {6, 0, 6, 1, 2, 3, 6, 4, 6, 6, 5, 6};
  210. static int cubeToPlane[MAXFACES] = {1, 3, 4, 5, 7, 10};
  211. static XPoint diamondUnit[MAXORIENT + 1] =
  212.     {{0, 1}, {1, -1}, {1, 1}, {-1, 1}, {-1, -1}},
  213.   triangleUnit[MAXORIENT][4] = {
  214.     {{2, 0}, { 1,  0}, { 0,  1}, {-1, -1}},
  215.     {{3, 2}, { 0,  1}, {-1,  0}, { 1, -1}},
  216.     {{1, 3}, {-1,  0}, { 0, -1}, { 1,  1}},
  217.     {{0, 1}, { 0, -1}, { 1,  0}, {-1,  1}}
  218.   },
  219.   letterUnit[MAXCUBES] = {{2, 0}, {2, 2}, {0, 2}, {0, 0}, {1, 1}};
  220. static XPoint diamondList[MAXORIENT + 1], triangleList[MAXORIENT][4],
  221.   letterList[MAXCUBES], offsetList[MAXCUBES];
  222.  
  223. static void InitializeSkewb2D(request, new)
  224.   Widget request, new;
  225. {
  226.   Skewb2DWidget w = (Skewb2DWidget) new;
  227.  
  228.   w->skewb.dim = 2;
  229.   ResizeSkewb2D(w);
  230. }
  231.  
  232. static void ResizeSkewb2D(w)
  233.   Skewb2DWidget w;
  234. {
  235.   w->skewb.delta = 3;
  236.   w->skewb.vertical = (w->core.height >= w->core.width);
  237.   if (w->skewb.vertical)
  238.     w->skewb2d.faceLength = MIN(w->core.height / MAXY, w->core.width / MAXX);
  239.   else
  240.     w->skewb2d.faceLength = MIN(w->core.height / MAXX, w->core.width / MAXY);
  241.   w->skewb2d.faceLength = MAX(w->skewb2d.faceLength - w->skewb.delta - 1, 0);
  242.   w->skewb2d.diamondLength = w->skewb2d.faceLength - w->skewb.delta;
  243.   w->skewb2d.viewLength = w->skewb2d.faceLength + w->skewb.delta;
  244.   if (w->skewb.vertical) {
  245.     w->skewb.puzzleSize.x = MAXX * (w->skewb2d.viewLength - 1) +
  246.       w->skewb.delta;
  247.     w->skewb.puzzleSize.y = MAXY * (w->skewb2d.viewLength - 1) +
  248.       w->skewb.delta;
  249.   } else {
  250.     w->skewb.puzzleSize.x = MAXY * (w->skewb2d.viewLength - 1) +
  251.       w->skewb.delta;
  252.     w->skewb.puzzleSize.y = MAXX * (w->skewb2d.viewLength - 1) +
  253.       w->skewb.delta;
  254.   }
  255.   w->skewb.puzzleOffset.x = ((int) w->core.width - w->skewb.puzzleSize.x)
  256.     / 2;
  257.   w->skewb.puzzleOffset.y = ((int) w->core.height - w->skewb.puzzleSize.y)
  258.     / 2;
  259.   ResizePolyhedrons(w);
  260. }
  261.  
  262. static void ExposeSkewb2D(new, event, region)
  263.   Widget new;
  264.   XEvent *event;
  265.   Region region; /* Not used */
  266. {
  267.   Skewb2DWidget w = (Skewb2DWidget) new;
  268.  
  269.   if (w->core.visible) {
  270.     DrawFrame(w, w->skewb.puzzleGC);
  271.     DrawAllPolyhedrons((SkewbWidget) w);
  272.   }
  273. }
  274.  
  275. static Boolean SetValuesSkewb2D(current, request, new)
  276.   Widget current, request, new;
  277. {
  278.   Skewb2DWidget c = (Skewb2DWidget) current, w = (Skewb2DWidget) new;
  279.   Boolean redraw = FALSE;
  280.  
  281.   if (w->skewb2d.diamondLength != c->skewb2d.diamondLength) {
  282.     ResizeSkewb2D(w);
  283.     redraw = TRUE;
  284.   }
  285.   return (redraw);
  286. }
  287.  
  288. static void MoveSkewb2DTl(w, event, args, nArgs)
  289.   Skewb2DWidget w;
  290.   XEvent *event;
  291.   char *args[];
  292.   int nArgs;
  293. {
  294.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, TL,
  295.     (int) (event->xkey.state & ControlMask), FALSE);
  296. }
  297.  
  298. static void MoveSkewb2DTop(w, event, args, nArgs)
  299.   Skewb2DWidget w;
  300.   XEvent *event;
  301.   char *args[];
  302.   int nArgs;
  303. {
  304.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, TOP,
  305.     (int) (event->xkey.state & ControlMask),
  306.     (int) (event->xkey.state &
  307.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  308. }
  309.  
  310. static void MoveSkewb2DTr(w, event, args, nArgs)
  311.   Skewb2DWidget w;
  312.   XEvent *event;
  313.   char *args[];
  314.   int nArgs;
  315. {
  316.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, TR,
  317.     (int) (event->xkey.state & ControlMask), FALSE);
  318. }
  319.  
  320. static void MoveSkewb2DLeft(w, event, args, nArgs)
  321.   Skewb2DWidget w;
  322.   XEvent *event;
  323.   char *args[];
  324.   int nArgs;
  325. {
  326.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, LEFT,
  327.     (int) (event->xkey.state & ControlMask),
  328.     (int) (event->xkey.state &
  329.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  330. }
  331.  
  332. static void MoveSkewb2dRight(w, event, args, nArgs)
  333.   Skewb2DWidget w;
  334.   XEvent *event;
  335.   char *args[];
  336.   int nArgs;
  337. {
  338.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, RIGHT,
  339.     (int) (event->xkey.state & ControlMask),
  340.     (int) (event->xkey.state &
  341.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  342. }
  343.  
  344. static void MoveSkewb2DBl(w, event, args, nArgs)
  345.   Skewb2DWidget w;
  346.   XEvent *event;
  347.   char *args[];
  348.   int nArgs;
  349. {
  350.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, BL,
  351.     (int) (event->xkey.state & ControlMask), FALSE);
  352. }
  353.  
  354. static void MoveSkewb2DBottom(w, event, args, nArgs)
  355.   Skewb2DWidget w;
  356.   XEvent *event;
  357.   char *args[];
  358.   int nArgs;
  359. {
  360.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, BOTTOM,
  361.     (int) (event->xkey.state & ControlMask),
  362.     (int) (event->xkey.state &
  363.       (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)));
  364. }
  365.  
  366. static void MoveSkewb2DBr(w, event, args, nArgs)
  367.   Skewb2DWidget w;
  368.   XEvent *event;
  369.   char *args[];
  370.   int nArgs;
  371. {
  372.   MoveSkewbInput((SkewbWidget) w, event->xbutton.x, event->xbutton.y, BR,
  373.     (int) (event->xkey.state & ControlMask), FALSE);
  374. }
  375.  
  376. static void ResizePolyhedrons(w)
  377.   Skewb2DWidget w;
  378. {
  379.   int i, j;
  380.  
  381.   w->skewb.orientLineLength = w->skewb2d.diamondLength / 8;
  382.   w->skewb.letterOffset.x = -2;
  383.   w->skewb.letterOffset.y = 4;
  384.   for (i = 0; i <= MAXORIENT; i++) {
  385.     diamondList[i].x = diamondUnit[i].x * (w->skewb2d.diamondLength / 2 -
  386.       w->skewb.delta);
  387.     diamondList[i].y = diamondUnit[i].y * (w->skewb2d.diamondLength / 2 -
  388.       w->skewb.delta);
  389.   }
  390.   for (i = 0; i < MAXORIENT; i++) {
  391.     for (j = 0; j <= 3; j++) {
  392.       triangleList[i][j].x = triangleUnit[i][j].x *
  393.         (w->skewb2d.diamondLength / 2 - 3 * w->skewb.delta);
  394.       triangleList[i][j].y = triangleUnit[i][j].y *
  395.         (w->skewb2d.diamondLength / 2 - 3 * w->skewb.delta);
  396.     }
  397.   }
  398.  
  399.   for (i = 0; i < MAXORIENT; i++) {
  400.     if (letterUnit[i].x == 0)
  401.       letterList[i].x = w->skewb2d.diamondLength / 8 +
  402.         w->skewb.letterOffset.x;
  403.     else if (letterUnit[i].x == 2)
  404.       letterList[i].x = 7 * w->skewb2d.diamondLength / 8 - 2 +
  405.         w->skewb.letterOffset.x;
  406.     if (letterUnit[i].y == 0)
  407.       letterList[i].y = w->skewb2d.diamondLength / 8 + 2 +
  408.         w->skewb.letterOffset.y;
  409.     else if (letterUnit[i].y == 2)
  410.       letterList[i].y = 7 * w->skewb2d.diamondLength / 8 - 3 +
  411.         w->skewb.letterOffset.y;
  412.  
  413.     if (triangleUnit[i][0].x == 0)
  414.       offsetList[i].x = w->skewb.delta - 1;
  415.     else if (triangleUnit[i][0].x == 1)
  416.       offsetList[i].x = w->skewb2d.diamondLength / 2 -
  417.         2 * w->skewb.delta - 1;
  418.     else if (triangleUnit[i][0].x == 2)
  419.       offsetList[i].x = w->skewb2d.diamondLength / 2 +
  420.         2 * w->skewb.delta;
  421.     else if (triangleUnit[i][0].x == 3)
  422.       offsetList[i].x = w->skewb2d.diamondLength - w->skewb.delta - 1;
  423.     if (triangleUnit[i][0].y == 0)
  424.       offsetList[i].y = w->skewb.delta - 1;
  425.     else if (triangleUnit[i][0].y == 1)
  426.       offsetList[i].y = w->skewb2d.diamondLength / 2 -
  427.         2 * w->skewb.delta - 1;
  428.     else if (triangleUnit[i][0].y == 2)
  429.       offsetList[i].y = w->skewb2d.diamondLength / 2 +
  430.         2 * w->skewb.delta - 1;
  431.     else if (triangleUnit[i][0].y == 3)
  432.       offsetList[i].y = w->skewb2d.diamondLength - w->skewb.delta - 2;
  433.   }
  434.   if (diamondUnit[0].x == 0)
  435.     offsetList[MAXORIENT].x = w->skewb.delta - 2;
  436.   else if (diamondUnit[0].x == 1)
  437.     offsetList[MAXORIENT].x = w->skewb2d.diamondLength / 2 - 1;
  438.   if (diamondUnit[0].y == 0)
  439.     offsetList[MAXORIENT].y = w->skewb.delta - 2;
  440.   else if (diamondUnit[0].y == 1)
  441.     offsetList[MAXORIENT].y = w->skewb2d.diamondLength / 2 - 2;
  442.   if (letterUnit[MAXORIENT].x == 1)
  443.     letterList[MAXORIENT].x = w->skewb2d.diamondLength / 2 - 2 +
  444.       w->skewb.letterOffset.x;
  445.   if (letterUnit[MAXORIENT].y == 1)
  446.     letterList[MAXORIENT].y = w->skewb2d.diamondLength / 2 - 2 +
  447.       w->skewb.letterOffset.y;
  448. }
  449.  
  450. int SelectPolyhedrons2D(w, x, y, face, position)
  451.   Skewb2DWidget w;
  452.   int x, y;
  453.   int *face;
  454.   int *position;
  455. {
  456.   int faceX, faceY, i, j;
  457.  
  458.   x -= w->skewb.puzzleOffset.x;
  459.   y -= w->skewb.puzzleOffset.y;
  460.   faceX = x / w->skewb2d.viewLength;
  461.   faceY = y / w->skewb2d.viewLength;
  462.   i = x - faceX * w->skewb2d.viewLength;
  463.   j = y - faceY * w->skewb2d.viewLength;
  464.   if (i - j > w->skewb2d.viewLength / 2 - 3)
  465.     *position = TR;
  466.   else if (i + j > 3 * w->skewb2d.viewLength / 2)
  467.     *position = BR;
  468.   else if (j - i > w->skewb2d.viewLength / 2 - 2)
  469.     *position = BL;
  470.   else if (i + j < w->skewb2d.viewLength / 2 + 7)
  471.     *position = TL;
  472.   else
  473.     *position = MAXORIENT;
  474.   if ((faceX != 1 && faceY != 1) ||
  475.       (faceX >= 3 && w->skewb.vertical) ||
  476.       (faceY >= 3 && !w->skewb.vertical))
  477.     return FALSE;
  478.   *face = planeToCube[faceX + faceY * MAXX];
  479.   if (faceX == 3) {
  480.     *face = MAXFACES - 1;
  481.     if (*position != MAXORIENT)
  482.       *position = (*position + HALF) % MAXORIENT;
  483.   }
  484.   return TRUE;
  485. }
  486.  
  487. int NarrowSelection2D(w, face, position, direction)
  488.   Skewb2DWidget w;
  489.   int *face;
  490.   int *position;
  491.   int *direction;
  492. {
  493.   if (*face == MAXFACES - 1 && *direction < MAXORIENT && !w->skewb.vertical) {
  494.     if (*direction < MAXORIENT)
  495.       *direction = (*direction + HALF) % MAXORIENT;
  496.     else if (*direction >= 2 * MAXORIENT)
  497.       *direction = 2 * MAXORIENT + (*direction + HALF) % MAXORIENT;
  498.   }
  499.   if (*position != MAXORIENT) {
  500.     if (*direction == CW)
  501.       *direction = (*position + 1) % MAXORIENT;
  502.     else if (*direction == CCW)
  503.       *direction = (*position + 3) % MAXORIENT;
  504.     else if (*direction < MAXORIENT && !((*direction + *position) % 2))
  505.       return FALSE;
  506.   }
  507.   return TRUE;
  508. }
  509.  
  510. static void DrawFrame(w, gc)
  511.   Skewb2DWidget w;
  512.   GC gc;
  513. {
  514.   int i;
  515.   XPoint pos[MAXXY + 1], letters;
  516.   
  517.   for (i = 0; i <= MAXXY; i++) {
  518.     pos[i].x = i * w->skewb2d.viewLength + w->skewb.puzzleOffset.x;
  519.     pos[i].y = i * w->skewb2d.viewLength + w->skewb.puzzleOffset.y;
  520.   }
  521.   XDrawLine(XtDisplay(w), XtWindow(w), gc,
  522.     pos[1].x, pos[0].y, pos[2].x, pos[0].y);
  523.   XDrawLine(XtDisplay(w), XtWindow(w), gc,
  524.     pos[3].x, pos[1].y, pos[3].x, pos[2].y);
  525.   XDrawLine(XtDisplay(w), XtWindow(w), gc,
  526.     pos[1].x, pos[3].y, pos[2].x, pos[3].y);
  527.   XDrawLine(XtDisplay(w), XtWindow(w), gc,
  528.     pos[0].x, pos[1].y, pos[0].x, pos[2].y);
  529.   letters.x = pos[0].x + w->skewb2d.viewLength / 2 - w->skewb.delta;
  530.   letters.y = pos[0].y + w->skewb2d.viewLength / 2;
  531.   XDrawString(XtDisplay(w), XtWindow(w), gc,
  532.     (int) (letters.x + 5 * w->skewb.letterOffset.x),
  533.     (int) (letters.y + w->skewb.letterOffset.y), "Front", 5);
  534.   letters.x = pos[2].x + w->skewb2d.viewLength / 2 - w->skewb.delta;
  535.   letters.y = pos[2].y + w->skewb2d.viewLength / 2;
  536.   XDrawString(XtDisplay(w), XtWindow(w), gc,
  537.     (int) (letters.x + 4 * w->skewb.letterOffset.x),
  538.     (int) (letters.y + w->skewb.letterOffset.y), "Back", 4);
  539.   if (w->skewb.vertical) {
  540.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  541.       pos[1].x, pos[0].y, pos[1].x, pos[4].y);
  542.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  543.       pos[2].x, pos[0].y, pos[2].x, pos[4].y);
  544.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  545.       pos[0].x, pos[1].y, pos[3].x, pos[1].y);
  546.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  547.       pos[0].x, pos[2].y, pos[3].x, pos[2].y);
  548.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  549.       pos[1].x, pos[4].y, pos[2].x, pos[4].y);
  550.   } else {
  551.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  552.       pos[0].x, pos[1].y, pos[4].x, pos[1].y);
  553.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  554.       pos[0].x, pos[2].y, pos[4].x, pos[2].y);
  555.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  556.       pos[1].x, pos[0].y, pos[1].x, pos[3].y);
  557.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  558.       pos[2].x, pos[0].y, pos[2].x, pos[3].y);
  559.     XDrawLine(XtDisplay(w), XtWindow(w), gc,
  560.       pos[4].x, pos[1].y, pos[4].x, pos[2].y);
  561.   }
  562. }   
  563.  
  564. void DrawDiamond2D(w, face)
  565.   Skewb2DWidget w;
  566.   int face;
  567. {
  568.   int dx, dy, orient;
  569.  
  570.   orient = w->skewb.cubeLoc[face][MAXORIENT].rotation;
  571.   if (w->skewb.vertical || face != MAXFACES - 1) {
  572.     dx = (cubeToPlane[face] % MAXX) * w->skewb2d.viewLength +
  573.       w->skewb.delta;
  574.     dy = (cubeToPlane[face] / MAXX) * w->skewb2d.viewLength +
  575.       w->skewb.delta;
  576.   } else {
  577.     dx = (cubeToPlane[face] / MAXX) * w->skewb2d.viewLength +
  578.       w->skewb.delta;
  579.     dy = (cubeToPlane[face] % MAXX) * w->skewb2d.viewLength +
  580.       w->skewb.delta;
  581.     orient = (orient + HALF) % STRT;
  582.   }
  583.   dx += w->skewb.puzzleOffset.x + w->skewb.delta;
  584.   dy += w->skewb.puzzleOffset.y + w->skewb.delta;
  585.   diamondList[0].x = offsetList[MAXORIENT].x + dx;
  586.   diamondList[0].y = offsetList[MAXORIENT].y + dy;
  587.   XFillPolygon(XtDisplay(w), XtWindow(w),
  588.      w->skewb.faceGC[w->skewb.cubeLoc[face][MAXORIENT].face],
  589.      diamondList, 4, Convex, CoordModePrevious);
  590.   XDrawLines(XtDisplay(w), XtWindow(w),
  591.      w->skewb.borderGC, diamondList, 5, CoordModePrevious);
  592.   if (w->skewb.depth == 1 || w->skewb.mono) {
  593.     int letterX, letterY;
  594.     char buf[2];
  595.  
  596.     (void) sprintf(buf, "%c",
  597.              w->skewb.faceName[w->skewb.cubeLoc[face][MAXORIENT].face][0]);
  598.     letterX = dx + letterList[MAXORIENT].x;
  599.     letterY = dy + letterList[MAXORIENT].y;
  600.     XDrawString(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  601.       letterX, letterY, buf, 1);
  602.   }
  603.   if (w->skewb.orient)
  604.     DrawOrientLine(w, MAXORIENT, orient, dx, dy);
  605. }
  606.  
  607. void DrawTriangle2D(w, face, position, offset)
  608.   Skewb2DWidget w;
  609.   int face, position, offset;
  610. {
  611.   int dx, dy, letterX, letterY, orient, newCorner;
  612.  
  613.   orient = w->skewb.cubeLoc[face][position].rotation;
  614.   if (w->skewb.vertical || face != MAXFACES - 1) {
  615.     dx = (cubeToPlane[face] % MAXX) * w->skewb2d.viewLength +
  616.       w->skewb.delta - 1;
  617.     dy = (cubeToPlane[face] / MAXX) * w->skewb2d.viewLength +
  618.       w->skewb.delta - 1;
  619.     newCorner = position;
  620.   } else {
  621.     dx = (cubeToPlane[face] / MAXX) * w->skewb2d.viewLength +
  622.       w->skewb.delta - 1;
  623.     dy = (cubeToPlane[face] % MAXX) * w->skewb2d.viewLength +
  624.       w->skewb.delta - 1;
  625.     newCorner = (position + HALF) % STRT;
  626.     orient = (orient + HALF) % STRT;
  627.   }
  628.   dx += w->skewb.puzzleOffset.x + w->skewb.delta;
  629.   dy += w->skewb.puzzleOffset.y + w->skewb.delta;
  630.   letterX = dx + letterList[newCorner].x;
  631.   letterY = dy + letterList[newCorner].y;
  632.   triangleList[newCorner][0].x = offsetList[newCorner].x + dx;
  633.   triangleList[newCorner][0].y = offsetList[newCorner].y + dy;
  634.   if (offset) {
  635.     XFillPolygon(XtDisplay(w), XtWindow(w),
  636.       w->skewb.borderGC,
  637.       triangleList[newCorner], 3, Convex, CoordModePrevious);
  638.     XDrawLines(XtDisplay(w), XtWindow(w),
  639.       w->skewb.faceGC[w->skewb.cubeLoc[face][position].face],
  640.       triangleList[newCorner], 4, CoordModePrevious);
  641.   } else {
  642.     XFillPolygon(XtDisplay(w), XtWindow(w),
  643.       w->skewb.faceGC[w->skewb.cubeLoc[face][position].face],
  644.       triangleList[newCorner], 3, Convex, CoordModePrevious);
  645.     XDrawLines(XtDisplay(w), XtWindow(w),
  646.       w->skewb.borderGC, triangleList[newCorner], 4, CoordModePrevious);
  647.   }
  648.   if (w->skewb.depth == 1 || w->skewb.mono) {
  649.     char buf[2];
  650.  
  651.     (void) sprintf(buf, "%c",
  652.              w->skewb.faceName[w->skewb.cubeLoc[face][position].face][0]);
  653.     XDrawString(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  654.       letterX, letterY, buf, 1);
  655.   }
  656.   if (w->skewb.orient)
  657.     DrawOrientLine(w, newCorner, orient,
  658.       letterX - w->skewb.letterOffset.x, letterY - w->skewb.letterOffset.y);
  659. }
  660.  
  661. static void DrawOrientLine(w, cube, orient, dx, dy)
  662.   Skewb2DWidget w;
  663.   int cube, orient, dx, dy;
  664. {
  665.   if (cube == MAXORIENT)
  666.     switch (orient) {
  667.       case TR:
  668.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  669.                   dx + w->skewb2d.diamondLength / 2 - 2,
  670.                   dy + w->skewb.delta - 2,
  671.                   dx + w->skewb2d.diamondLength / 2 - 2,
  672.                   dy + w->skewb.delta + w->skewb.orientLineLength);
  673.         return;
  674.       case BR:
  675.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  676.                   dx + w->skewb2d.diamondLength - 2,
  677.                   dy + w->skewb2d.diamondLength / 2 - 2,
  678.                   dx + w->skewb2d.diamondLength -
  679.                     w->skewb.orientLineLength - 7,
  680.                   dy + w->skewb2d.diamondLength / 2 - 2);
  681.         return;
  682.       case BL:
  683.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  684.                   dx + w->skewb2d.diamondLength / 2 - 2,
  685.                   dy + w->skewb2d.diamondLength - 2,
  686.                   dx + w->skewb2d.diamondLength / 2 - 2,
  687.                   dy + w->skewb2d.diamondLength -
  688.                     w->skewb.orientLineLength - 7);
  689.         return;
  690.       case TL:
  691.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  692.                   dx + w->skewb.delta - 2,
  693.                   dy + w->skewb2d.diamondLength / 2 - 2,
  694.                   dx + w->skewb.delta + w->skewb.orientLineLength,
  695.                   dy + w->skewb2d.diamondLength / 2 - 2);
  696.         return;
  697.       default:
  698.         (void) printf("DrawOrientLine: orient %d\n", orient);
  699.     }
  700.   else /* cube != MAXORIENT */
  701.     switch (orient) {
  702.       case TR:
  703.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  704.                   dx, 
  705.                   dy - w->skewb.delta,
  706.                   dx,
  707.                   dy - w->skewb.delta - w->skewb.orientLineLength / 2);
  708.         return;
  709.       case BR:
  710.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  711.                   dx + w->skewb.delta,
  712.                   dy,
  713.                   dx + w->skewb.delta + w->skewb.orientLineLength / 2,
  714.                   dy);
  715.         return;
  716.       case BL:
  717.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  718.                   dx,
  719.                   dy + w->skewb.delta,
  720.                   dx,
  721.                   dy + w->skewb.delta + w->skewb.orientLineLength / 2);
  722.         return;
  723.       case TL:
  724.         XDrawLine(XtDisplay(w), XtWindow(w), w->skewb.inverseGC,
  725.                   dx - w->skewb.delta,
  726.                   dy,
  727.                   dx - w->skewb.delta - w->skewb.orientLineLength / 2,
  728.                   dy);
  729.         return;
  730.       default:
  731.         (void) printf("DrawOrientLine: orient %d\n", orient);
  732.     }
  733. }
  734.